<?php

namespace app\admin\service;

use app\common\configs\SettingConf;
use app\common\configs\WeChatApi;
use app\common\model\trCache;
use app\common\model\trSystemSet;
use app\common\util\ErrorCode;
use app\common\util\Tools;
use app\common\util\WxBizMsgCrypt;
use app\common\util\WxOpenUtil;

/**
 * Class Auth
 * @package app\admin\service
 * 微信服务类
 */
class WxService
{
    // 获取第三方授权地址
    public function getAuthorizationUrl($params){
        if(!isset($params['url'])){
            return ErrorCode::code("params_not_exist", "url");
        }
        $returnData = ErrorCode::$errorCode["success"];
        $url = request()->domain() . request()->server("SCRIPT_NAME") . "/admin/event/notify?mall_id=".request()->mallData["id"]."&url=".urlencode($params["url"]);
        $res = WxOpenUtil::getInstance()->getAuthorizationUrl($url);
        if(isset($res["code"])){
            return $res;
        }
        $returnData["data"] = ["authUrl" => $res];
        return $returnData;
    }

    // 微信 授权给第三方平台 的回调处理方法
    public function wxNotify($params){
        if(!empty($params["auth_code"])) {
            $util = WxOpenUtil::getInstance();
            $res = $util->getQueryAuth($params["auth_code"]);
            if (!isset($res["code"])) {
                $authResult = $util->getAuthorizerInfo($res["authorizer_appid"]);
                unset($util);
                if(!isset($authResult["code"])) {
                    $data = array_merge(
                        SettingConf::$baseConfigArr[SettingConf::WX_CHAT_APP_CONFIG],
                        (array)trSystemSet::getValue(SettingConf::WX_CHAT_APP_CONFIG),
                        ["appId" => $res["authorizer_appid"]]
                    );
                    trSystemSet::toSave($data, SettingConf::WX_CHAT_APP_CONFIG);
                }else{
                    Tools::writeLog("-第三方授权后err：" . var_export($authResult, true), "wxAuthNotice.txt");
                }
            }else{
                Tools::writeLog("-第三方授权后err：" . var_export($res, true), "wxAuthNotice.txt");
            }
        }else{
            Tools::writeLog("-第三方授权后err：" . var_export($params, true), "wxAuthNotice.txt");
        }
        if(isset($params["url"])) {
            if(request()->server("IS_SCF")) {
                return " <script language = 'javascript' type = 'text/javascript'>window.location.href = '{$params["url"]}';</script>";
            }else {
                header('Location: ' . $params["url"]);exit;
            }
        }
        return true;
    }

    // 微信 授权事件接收URL
    public function wxAuthEvent($params){
        try {
            if(!empty($params["msg_signature"])) {
                $xml = file_get_contents('php://input');
                $xml = $xml ?: $params["xml"];
                $wx = new WxBizMsgCrypt();
                $res = $wx->decryptMsg($params["msg_signature"], $params["timestamp"], $params["nonce"], $xml, $result);
                if ($res == "0") {
                    $data = $this->fromXml($result);
                    if ($data["InfoType"] == "component_verify_ticket") { // 第三方票据
                        trCache::saveCache(["key" => "ComponentVerifyTicket_{$data["AppId"]}", "value" => $data["ComponentVerifyTicket"], "time" => 1800, "mall_id" => 0]); // 存放30分钟
                    } else if ($data["InfoType"] == "notify_third_fasteregister") { // 快速创建小程序结果通知

                    } elseif ($data["InfoType"] == "unauthorized" && !empty($data["AuthorizerAppid"])) { // 取消授权

                    }
                } else {
                    Tools::writeLog("auth wx 解密失败：" . (isset(WxBizMsgCrypt::$msg[$res]) ? WxBizMsgCrypt::$msg[$res] : $res).var_export($params, true), "wxAuthEventAccept.txt");
                }
            }
        }catch (\Exception $e){
            Tools::writeLog("执行失败：" . $e->getTraceAsString(), "wxAuthEventAcceptErr.txt");
        }
        return "success";
    }

    // 微信 消息与事件接收URL
    public function wxMessage($appId, $params){
        $returnMsg = "success";
        try {
            if(!empty($params["msg_signature"])) {
                $xml = file_get_contents('php://input');
                $xml = $xml ?: $params["xml"];
                $wx = new WxBizMsgCrypt();
                $res = $wx->decryptMsg($params["msg_signature"], $params["timestamp"], $params["nonce"], $xml, $result);
                if ($res == "0") {
                    $data = $this->fromXml($result);
                    if (in_array($appId, ["wx570bc396a51b8ff8", "wxd101a85aa106f53e"])) { // 全网发布的测试号，wxd101a85aa106f53e小程序，wx570bc396a51b8ff8公众号
                        $returnMsg = $this->handleAllNetworkCheck($wx, $data);
                    } else {
                    }
                } else {
                    Tools::writeLog("auth wx 解密失败：" . (isset(WxBizMsgCrypt::$msg[$res]) ? WxBizMsgCrypt::$msg[$res] : $res) . var_export($params, true), "wxMessageAccept.txt");
                }
            }
        }catch (\Exception $e){
            Tools::writeLog("执行失败：" . $e->getTraceAsString(), "wxMessageAcceptErr.txt");
        }
        return $returnMsg;
    }

    public function handleAllNetworkCheck(WxBizMsgCrypt $wx, $data){
        if($data["MsgType"] == "text" && strpos($data["Content"], "QUERY_AUTH_CODE:") !== false) {
            $data["Content"] = substr($data["Content"], strlen("QUERY_AUTH_CODE:"));
            $res = WxOpenUtil::getInstance()->getQueryAuth($data["Content"]);
            if(isset($res["authorizer_access_token"])) {
                $url = WeChatApi::$weChat_conf["custom_send"] . "?access_token={$res["authorizer_access_token"]}";
                $result = Tools::curl($url, json_encode(["touser" => $data["FromUserName"], "msgtype" => "text", "text" => ["content" => $data["Content"] . "_from_api"]]));
                Tools::writeLog("全网发布中：{$url} -- " . var_export($data, true) . var_export($res, true) . var_export($result, true), "handleAllNetworkCheck.txt");
            }
            return "success";
        }elseif($data["MsgType"] == "text" && $data["Content"] == "TESTCOMPONENT_MSG_TYPE_TEXT"){ // 文本回复
            $data["Content"] = "TESTCOMPONENT_MSG_TYPE_TEXT_callback";
            $toUserName = $data["ToUserName"];
            $data["ToUserName"] = $data["FromUserName"];
            $data["FromUserName"] = $toUserName;
            $data["CreateTime"] = time();
            $xml = $this->toXml($data);
            $res = $wx->encryptMsg($xml, $data["CreateTime"], rand(1000, 9999), $encryptMsg);
            Tools::writeLog("全网发布中-文本回复： -- ".var_export($data,true).var_export($encryptMsg,true).var_export($res,true), "handleAllNetworkCheck.txt");
            if($res == "0"){
                return $encryptMsg;
            }
        }
        return "success";
    }

    public function toXml($values)
    {

        $xml = "<xml>";
        foreach ($values as $key=>$val)
        {
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }

    public function fromXml($xml)
    {
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $values;
    }
}